From d953ce87750f5be9a851df22f2f21a100f964ec1 Mon Sep 17 00:00:00 2001 From: Michael Natterer Date: Wed, 14 Mar 2007 13:55:12 +0000 Subject: [PATCH] Make gtk_widget_set_extension_events() work on already realized widgets 2007-03-14 Michael Natterer Make gtk_widget_set_extension_events() work on already realized widgets (bug #379550, Tommi Komulainen) * gdk/x11/gdkinput.c (gdk_input_set_extension_events): allow to be called multiple times without leaking and work correctly when already realized (don't rely on a configure event following). * gtk/gtkwidget.c (gtk_widget_set_extension_events_internal): new internal function which walks the GdkWindow tree and sets the extension events on all windows that belong to the widget. (gtk_widget_realize) (gtk_widget_set_extension_events): use the new function. svn path=/trunk/; revision=17515 --- ChangeLog | 16 +++++++++++ gdk/x11/gdkinput.c | 31 ++++++++++++++------ gtk/gtkwidget.c | 71 +++++++++++++++++++++++++++++++++++----------- 3 files changed, 93 insertions(+), 25 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5bb8b14a13..9fbc61d17c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2007-03-14 Michael Natterer + + Make gtk_widget_set_extension_events() work on already realized + widgets (bug #379550, Tommi Komulainen) + + * gdk/x11/gdkinput.c (gdk_input_set_extension_events): allow to be + called multiple times without leaking and work correctly when + already realized (don't rely on a configure event following). + + * gtk/gtkwidget.c (gtk_widget_set_extension_events_internal): new + internal function which walks the GdkWindow tree and sets the + extension events on all windows that belong to the widget. + + (gtk_widget_realize) + (gtk_widget_set_extension_events): use the new function. + 2007-03-14 Emmanuele Bassi Various clean ups in the GtkRecent code. (see #338843) diff --git a/gdk/x11/gdkinput.c b/gdk/x11/gdkinput.c index f4d30cb209..8d87479f0e 100644 --- a/gdk/x11/gdkinput.c +++ b/gdk/x11/gdkinput.c @@ -313,29 +313,42 @@ gdk_input_set_extension_events (GdkWindow *window, gint mask, if (mode == GDK_EXTENSION_EVENTS_NONE) mask = 0; + iw = _gdk_input_window_find (window); + if (mask != 0) { - iw = g_new(GdkInputWindow,1); + if (!iw) + { + iw = g_new(GdkInputWindow,1); + + iw->window = window; + iw->mode = mode; - iw->window = window; - iw->mode = mode; + iw->obscuring = NULL; + iw->num_obscuring = 0; + iw->grabbed = FALSE; - iw->obscuring = NULL; - iw->num_obscuring = 0; - iw->grabbed = FALSE; + display_x11->input_windows = g_list_append(display_x11->input_windows,iw); + } - display_x11->input_windows = g_list_append(display_x11->input_windows,iw); window_private->extension_events = mask; +#ifndef XINPUT_NONE /* Add enter window events to the event mask */ - /* FIXME, this is not needed for XINPUT_NONE */ + /* this is not needed for XINPUT_NONE */ gdk_window_set_events (window, gdk_window_get_events (window) | GDK_ENTER_NOTIFY_MASK); + + /* we might not receive ConfigureNotify so get the root_relative_geometry + * now, just in case */ + _gdk_input_get_root_relative_geometry (GDK_WINDOW_XDISPLAY (window), + GDK_WINDOW_XWINDOW (window), + &iw->root_x, &iw->root_y, NULL, NULL); +#endif /* !XINPUT_NONE */ } else { - iw = _gdk_input_window_find (window); if (iw) { display_x11->input_windows = g_list_remove(display_x11->input_windows,iw); diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index 2ea73c258f..f93b54e0d8 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -2618,6 +2618,51 @@ gtk_widget_unmap (GtkWidget *widget) } } +static void +gtk_widget_set_extension_events_internal (GtkWidget *widget, + GdkExtensionMode mode, + GList *window_list) +{ + GList *free_list = NULL; + GList *l; + + if (window_list == NULL) + { + if (!GTK_WIDGET_NO_WINDOW (widget)) + window_list = g_list_prepend (NULL, widget->window); + else + window_list = gdk_window_get_children (widget->window); + + free_list = window_list; + } + + for (l = window_list; l != NULL; l = l->next) + { + GdkWindow *window = l->data; + gpointer user_data; + + gdk_window_get_user_data (window, &user_data); + if (user_data == widget) + { + GList *children; + + gdk_input_set_extension_events (window, + gdk_window_get_events (window), + mode); + + children = gdk_window_get_children (window); + if (children) + { + gtk_widget_set_extension_events_internal (widget, mode, children); + g_list_free (children); + } + } + } + + if (free_list) + g_list_free (free_list); +} + /** * gtk_widget_realize: * @widget: a #GtkWidget @@ -2645,7 +2690,6 @@ gtk_widget_unmap (GtkWidget *widget) void gtk_widget_realize (GtkWidget *widget) { - gint events; GdkExtensionMode mode; GtkWidgetShapeInfo *shape_info; @@ -2691,16 +2735,9 @@ gtk_widget_realize (GtkWidget *widget) shape_info->offset_x, shape_info->offset_y); - if (!GTK_WIDGET_NO_WINDOW (widget)) - { - mode = gtk_widget_get_extension_events (widget); - if (mode != GDK_EXTENSION_EVENTS_NONE) - { - events = gtk_widget_get_events (widget); - gdk_input_set_extension_events (widget->window, events, mode); - } - } - + mode = gtk_widget_get_extension_events (widget); + if (mode != GDK_EXTENSION_EVENTS_NONE) + gtk_widget_set_extension_events_internal (widget, mode, NULL); } } @@ -6572,21 +6609,23 @@ gtk_widget_add_events (GtkWidget *widget, * * Sets the extension events mask to @mode. See #GdkExtensionMode * and gdk_input_set_extension_events(). - * **/ void gtk_widget_set_extension_events (GtkWidget *widget, GdkExtensionMode mode) { GdkExtensionMode *modep; - + g_return_if_fail (GTK_IS_WIDGET (widget)); - + modep = g_object_get_qdata (G_OBJECT (widget), quark_extension_event_mode); - + if (!modep) modep = g_slice_new (GdkExtensionMode); - + + if (GTK_WIDGET_REALIZED (widget)) + gtk_widget_set_extension_events_internal (widget, mode, NULL); + *modep = mode; g_object_set_qdata (G_OBJECT (widget), quark_extension_event_mode, modep); g_object_notify (G_OBJECT (widget), "extension-events"); -- 2.30.2